`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/04/27 10:03:07
// Design Name: 
// Module Name: MemOrIO
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module MemOrIO(
    //来自控制信号

    //我是不是有读取内存的权限
    input mRead, 
    //这个信号决定我是不是有把数据写进内存的权限
    input mWrite, 
    //这个信号决定我是不是要从io中读取数据
    input ioRead, 
    //这个信号决定我是不是要把一个数据通过io写出去
    input ioWrite, 
    
    //这个要和ALU_Result相连，是ALU算术或者逻辑运算的结果
    input[31:0] addr_in,
    //如果我要访问内存，那么这个就是内存的地址 
    output[31:0] addr_out,
    //从内存中读取的数
    input[31:0] m_rdata,
    //从io中读取的数
    input[15:0] io_rdata, 
    //我要写到寄存器组中的数
    output[31:0] r_wdata, 
    //从寄存器组中读取出来的数,主要是要写到内存或者是IO设备
    input[31:0] r_rdata, 
    //我要写到内存或者IO设备中的数，具体是哪个由控制信号决定
    output reg[31:0] write_data, 
    //如果我要通过io设备输出了，那么这个LEDCtrl就是高电平，表示我选中了LED作为输出设备
    output LEDCtrl,
    //如果我要通过IO设备输入了，那么这个SwitchCtrl就是高电平，表示我选中了开关作为输入设备
    output SwitchCtrl
);

//如果我ALU_Result输进来了，那么这肯定是地址运算的结果，就把它直接和内存地址这个信号相连就行。
assign addr_out = addr_in;

//这个是决定我要写进寄存器组中的数，如果ioRead为1，说明写进寄存器组中的数来自于IO设备，否则就来自于memory
assign r_wdata = (mRead == 0) ? ({16'h0000,io_rdata}) : (m_rdata);

//这个决定LED灯是不是作为输出设备，就看ioWrite的控制信号
assign LEDCtrl = (ioWrite == 1'b1) ? 1'b1 : 1'b0;

//这个决定Switch是不是作为输入设备
assign SwitchCtrl = (ioRead == 1'b1) ? 1'b1 : 1'b0;

//这个是决定写入的数据的
always @(*) begin
    //如果我开了向内存或者IO设备中写入数据的权限，我才能开始写
    if ((mWrite == 1'b1)||(ioWrite == 1'b1)) begin
        //如果是向内存中写，那我就直接把32位的r_rdata赋值给write_data就行了，如果是向输出设备写，那我就要留16位0比特
        write_data = (mWrite == 1'b1) ? r_rdata : {16'b0000000000000000,r_rdata[15:0]};
    end
    else begin
        write_data = 32'hZZZZZZZZ;
    end
end

endmodule
